﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

//int main()
//{
//	int a = 0x11223344;
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	char ch = 'a';
//	int* pa = &a;
//	char* pc = &ch;
//	printf("%p\n", pa);
//	printf("%p\n", &a);
//	printf("%p\n", pc);
//	printf("%p\n", &ch);
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int* pa = &a;
////	*pa = 20;
//	printf("%d\n", *pa=20);
//	return 0;
//}

//int main()
//{
//	int n = 20;
//	int* pn = &n;
//	printf("%zd\n", sizeof(pn));
//	return 0;
//}
//在32位机器上，有32根地址线，一个地址是32个bit位 ----- 4个字节就能存储
//在64位机器上，有64根地址线，一个地址是64个bit位 ----- 8个字节就能存储
//注意：指针变量的大小和类型事无关的，只要是指针类型的变量，在相同平台上，大小都是相同的
//int main()
//{
//	printf("%zd\n", sizeof(short*));
//	printf("%zd\n", sizeof(int*));
//	printf("%zd\n", sizeof(long*));
//	printf("%zd\n", sizeof(char*));
//	return 0;
//}

//int main()
//{
//	int a = 0x11223344;
//	int* pa = &a;
//	*pa = 0;
//	return 0;
//}

//int main()
//{
//	int a = 0x11223344;
//	char* pa = &a;
//	*pa = 0;
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	char* pb = &a;
//
//	//pa
//	printf("pa-1 = %p\n", pa - 1);
//	printf("pa   = %p\n", pa);
//	printf("pa+1 = %p\n", pa+1);
//
//	printf("\n");
//	//pb
//	printf("pb-1 = %p\n", pb - 1);
//	printf("pb   = %p\n", pb);
//	printf("pb+1 = %p\n", pb + 1);
//	return 0;
//}

//指针类型决定了指针向前或者向后走一步有多大距离
//int main()
//{
//	int n = 0x11223344;
//	int* pi = &n;
//	char* pc = &n;
//	
//	printf("&n  =  %p\n", &n);
//	printf("pi  =  %p\n", pi);
//	printf("pi+1 =  %p\n", pi+1);
//	
//	printf("p  =  %p\n", pc);
//	printf("pc+1 =  %p\n", pc + 1);
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	void* pb = &a;
//	return 0;
//}
//int main()
//{
//	int n = 10;
//	//int* pn = &n;
//	//char* pn = &n;
//	void* pn = &n;
//	*pn = 0;
//	return 0;
//}

//int main()
//{
//	int a = 0x11223344;
//	&a;  //取出a的地址
//	printf("%p\n", &a);
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int* pa = &a;//取出a的地址并存储在指针变量pa中
//	printf("%p\n", &a);
//	printf("%p\n", pa);
//	return 0;
//}

//int main()
//{
//	int a = 20;
//	int* pa = &a;
//	printf("%d\n", *pa);//通过地址找a
//	*pa = 30;    //通过地址找到a并修改a
//	printf("%d\n", a);//通过地址找a
//	return 0;
//}

//int main()
//{
//	printf("%zd\n", sizeof(short*));
//	printf("%zd\n", sizeof(int*));
//	printf("%zd\n", sizeof(long*));
//	printf("%zd\n", sizeof(char*));
//	printf("%zd\n", sizeof(float*));
//	printf("%zd\n", sizeof(double*));
//	return 0;
//}

//变量的意思是，它的值是可以改变的
//const 常属性 --- 被const 修饰后就具有常属性，不能被修改
//int main()
//{
//	const int num = 20; //是变量还是常量？
//	//在C语言中，这里的num是常变量，num的本质还是变量，因为有const修饰，编译器在语法上
//	// 不允许修改这个变量
//	// 在c++语言中，这里的num就是常量
//	//num = 20;
//	//只能读取，不可以被修改
//	printf("%d\n", num);
//	return 0;
//}

//int main()
//{
//	const int num = 10;
//	printf("%d\n", num);
//	int* p = &num;
//	*p = 30;
//	printf("%d\n", num);
//	return 0;
//}

//const 修饰指针有两种情况
//int const * p 
//int *const p
////左边  --  表示指针指向的内容不能通过指针来改变了，但是指针变量本身的值（地址）是可以改的
//int main()
//{
//	const int num = 10;
//	int n = 100;
//	const int* p = &num;
//	//p=  &n;
//	//*p = n;
//	//const 放 * 左边修饰的是 *p  但是对p不限制；
//	return 0;
//}


////右边  --- const 限制的是p(指针变量），但是指针指向的内容是可以通过指针变量来改变的
//int main()
//{
//	const int num = 10;
//	int n = 100;
//	int* const p = &num;
//	*p = 20;  //ok
//	//p = &n;
//	printf("%d\n", num);
//	return 0;
//}

//左右两边    --- 指针变量(p)(地址）不可以被修改，指针变量指向的内容也不可以被修改
//int main()
//{
//	const int num = 10;
//	int n = 100;
//	const int* const p = &num;
//	p = &n;
//	p = 200;
//	return 0;
//}

//int main()
//{
//	const int n = 10;
//	int m = 20;
//	printf("%d\n", n);
//	int* pn = &n;
//	pn = &m;
//	printf("%d\n", *pn);
//	return 0;
//}

//int main()
//{
//	const int n = 10;
//	printf("%d\n", n);
//	int* pn = &n;
//	*pn = 30;
//	printf("%d\n", n);
//	return 0;
//}


//指针 +- 整数
//采用指针的方式打印数组元素---通过起始地址
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	int* p = &arr[0];
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ",*(p+i));
//	}
//	return 0;
//}
//
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	int* p = &arr[0];
//	for (i = sz-1; i >=0; i--)
//	{
//		printf("%d ", *(p + i));
//	}
//	return 0;
//}
//
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	int* p = &arr[0];
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *p );
//		p ++;
//		缺陷就是，p值改变
//	}
//	return 0;
//}

//指针 - 指针（地址 - 地址 )得到指针和指针之间的元素个数（绝对值）
//运算的前提条件是，两个指针指向同一块空间；
//int main()
//{
//	int arr[10] = { 0 };
//	printf("%d\n", &arr[9] - &arr[0]);//9
//	printf("%d\n", &arr[0] - &arr[9]);//-9
//
//	return 0;
//}

//求字符串长度
//#include <stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = strlen(arr);
//	printf("%d \n", len);
//	//strlen 统计的是字符串中\0之前的字符个数
//	return 0;
//}

//size_t my_strlen(char* s)
//{
//	int count = 0;
//	while (*s != '\0')
//	{
//		count++;
//		s++;
//	}
//	return count;
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = my_strlen(arr);
//	printf("%zd\n", len);
//	return 0;
//}

//size_t my_strlen(char* s)
//{
//	char* start = s;
//	while (*s != '\0')
//		s++;
//	return s - start;
//}
//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = my_strlen(arr);
//	printf("%zd\n", len);
//	return 0;
//}

//指针关系运算
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	while (p < &arr[sz])
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}

//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	while (p < &arr[sz])
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}
// 

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int* p = &arr[sz - 1];
//	while (p >= &arr[0])//p >= arr
//	{
//		printf("%d ", *p);
//		p--;
//	}
//	return 0;
//}

//野指针
//未初始化
//int main()
//{
//	//int* p; //p是没有初始化的，p里边存放的地址是随机
//	//*p = 20;//非法访问，p就是野指针
//	//对这一块空间是没有访问权限的，不能访问它
//	int n = 233;
//	int* p = &n;
//	return 0;
//}

//指针越界访问
//还给操作系统了，没有对这个空间的使用权限

//int main()
//{
//	int a = 10;
//	int* p = &a;//明确的指向
//	int* p2 = NULL;//NULL 空指针
//	//*p2 = 200;
//	if (p2 != NULL)
//	{
//		*p2 = 200;
//	}
//	return 0;
//}


//int main()
//{
//	int* p;//没有const 修饰
//	int const* p;
//	const int* p;//const 放在*的左边做修饰
//	int* const p;//const 放在*的右边做修饰
//	return 0;
//}

//int main()
//{
//	int n = 100;
//	int m = 200;
//	int const* p = &n;
//	*p = 0;
//	p = &m;
//
//	return 0;
//}

//#include <assert.h>
//
//int main()
//{
//	int* p = NULL;
//	assert(p != NULL);
//	return 0;
//}



//my_strlen 求字符长度时，是不期望s指向的字符串被修改的！
//#include <assert.h>
//
//size_t my_strlen(const char* s)
//{
//	int count = 0;
//	assert(s != NULL);
//	while (*s != '\0')  //还可以直接写成*s
//	{
//		count++;
//		s++;
//	}
//	return count;
//}
//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = my_strlen(arr);
//	printf("%d \n", len);
//	return 0;
//}

//写⼀个函数，交换两个整型变量的值
//void swap(int x, int y)
//{
//	int z = 0;
//	z = x;
//	x = y;
//	y = z;
//}
//
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	printf("交换前：a=%d , b=%d\n", a, b);
//
//	swap(a, b);//传值调用
//
//	printf("交换后：a=%d , b=%d\n", a, b);
//	return 0;
//}

//void swap(int* pa, int* pb)
//{
//	int z = 0;
//	z = *pa;
//	*pa = *pb;
//	*pb = z;
//}
//
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	printf("交换前：a=%d , b=%d\n", a, b);
//
//	swap(&a,&b);//传址调用
//
//	printf("交换后：a=%d , b=%d\n", a, b);
//	return 0;
//}

//int Add(int x, int y)
//{
//	return x + y;
//}
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	int c = Add(a, b);
//	printf("%d \n", c);
//	return 0;
//}